home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / net / ds3100.md / netLERecv.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  10KB  |  360 lines

  1. /* netLERecv.c -
  2.  *
  3.  *    Routines to manage the receive unit of the AMD LANCE ethernet chip.
  4.  *
  5.  * Copyright (C) 1989 Digital Equipment Corporation.
  6.  * Permission to use, copy, modify, and distribute this software and
  7.  * its documentation for any purpose and without fee is hereby granted,
  8.  * provided that the above copyright notice appears in all copies.  
  9.  * Digital Equipment Corporation makes no representations about the
  10.  * suitability of this software for any purpose.  It is provided "as is"
  11.  * without express or implied warranty.
  12.  */
  13.  
  14. #ifndef lint
  15. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/net/ds3100.md/netLERecv.c,v 9.2 90/11/05 18:09:45 jhh Exp $ SPRITE (DECWRL)";
  16. #endif not lint
  17.  
  18. #include <sprite.h>
  19. #include <vm.h>
  20. #include <netLEInt.h>
  21. #include <sys.h>
  22. #include <list.h>
  23. #include <machMon.h>
  24.  
  25. /*
  26.  * Macro to step ring pointers.
  27.  */
  28. #define    NEXT_RECV(p)    ((p) == statePtr->recvDescLastPtr) ? \
  29.                 statePtr->recvDescFirstPtr : \
  30.             (Address)BUF_TO_ADDR(p, NET_LE_RECV_DESC_SIZE)
  31.  
  32.  
  33. /*
  34.  *----------------------------------------------------------------------
  35.  *
  36.  * AllocateRecvMem --
  37.  *
  38.  *    Allocate kernel memory for receive ring and data buffers.    
  39.  *
  40.  * Results:
  41.  *    None.
  42.  *
  43.  * Side effects:
  44.  *    Device state structure is updated.
  45.  *
  46.  *----------------------------------------------------------------------
  47.  */
  48. static void
  49. AllocateRecvMem(statePtr)
  50.     NetLEState        *statePtr; /* The state of the interface. */
  51. {
  52.     int            i;
  53.  
  54.     /*
  55.      * Allocate the ring of receive buffer descriptors.  The ring must start
  56.      * on 8-byte boundary.  
  57.      */
  58.     statePtr->recvDescFirstPtr = 
  59.     NetLEMemAlloc(NET_LE_NUM_RECV_BUFFERS * NET_LE_RECV_DESC_SIZE, FALSE);
  60.  
  61.     /*
  62.      * Allocate the receive buffers.
  63.      */
  64.     for (i = 0; i < NET_LE_NUM_RECV_BUFFERS; i++) {
  65.     statePtr->recvDataBuffer[i] = 
  66.         NetLEMemAlloc(NET_LE_RECV_BUFFER_SIZE, TRUE);
  67.     }
  68.     statePtr->recvMemAllocated = TRUE;
  69.     /*
  70.      * Allocate memory for the buffer to copy packets into after we
  71.      * receive them.
  72.      */
  73.     statePtr->recvBufPtr = (Address) malloc(NET_LE_RECV_BUFFER_SIZE + 2);
  74.     /*
  75.      * 2 byte align the recvBufPtr so that we can 4 byte align all words
  76.      * after the ethernet header.
  77.      */
  78.     statePtr->recvBufPtr += 2;
  79. }
  80.  
  81.  
  82. /*
  83.  *----------------------------------------------------------------------
  84.  *
  85.  * NetLERecvInit --
  86.  *
  87.  *    Initialize the receive buffer lists for the receive unit allocating
  88.  *    memory if need.
  89.  *
  90.  * Results:
  91.  *    None.
  92.  *
  93.  * Side effects:
  94.  *    The receive ring is initialized and the device state structure is
  95.  *    updated.
  96.  *
  97.  *----------------------------------------------------------------------
  98.  */
  99. void
  100. NetLERecvInit(statePtr)
  101.     NetLEState        *statePtr; /* The state of the interface. */
  102. {
  103.     int     bufNum;
  104.     Address    descPtr;
  105.  
  106.     if (!statePtr->recvMemAllocated) {
  107.     AllocateRecvMem(statePtr);
  108.     }
  109.     /*
  110.      * Initialize the state structure to point to the ring. recvDescFirstPtr
  111.      * is set by AllocateRecvMem() and never changed.
  112.      */
  113.     statePtr->recvDescLastPtr = (Address)
  114.     BUF_TO_ADDR(statePtr->recvDescFirstPtr,
  115.             (NET_LE_NUM_RECV_BUFFERS - 1) * NET_LE_RECV_DESC_SIZE);
  116.     statePtr->recvDescNextPtr = statePtr->recvDescFirstPtr;
  117.  
  118.     /* 
  119.      * Initialize the ring buffer descriptors.
  120.      */
  121.     descPtr = statePtr->recvDescFirstPtr;
  122.     for (bufNum = 0; 
  123.      bufNum < NET_LE_NUM_RECV_BUFFERS; 
  124.      bufNum++, descPtr += 2 * NET_LE_RECV_DESC_SIZE) { 
  125.      /*
  126.       * Point the descriptor at its buffer.
  127.       */
  128.     *BUF_TO_ADDR(descPtr,NET_LE_RECV_BUF_SIZE) =
  129.             -NET_LE_RECV_BUFFER_SIZE;
  130.     *BUF_TO_ADDR(descPtr,NET_LE_RECV_BUF_ADDR_LOW) =
  131.             BUF_TO_CHIP_ADDR(statePtr->recvDataBuffer[bufNum]) & 
  132.             0xFFFF;
  133.     *BUF_TO_ADDR(descPtr,NET_LE_RECV_STATUS) =
  134.         ((BUF_TO_CHIP_ADDR(statePtr->recvDataBuffer[bufNum]) >> 16) & 
  135.                         NET_LE_RECV_BUF_ADDR_HIGH) |
  136.             NET_LE_RECV_START_OF_PACKET |
  137.             NET_LE_RECV_END_OF_PACKET |
  138.             NET_LE_RECV_CHIP_OWNED;
  139.     }
  140.     descPtr = statePtr->recvDescFirstPtr;
  141.     statePtr->recvMemInitialized = TRUE;
  142. }
  143.  
  144.  
  145. /*
  146.  *----------------------------------------------------------------------
  147.  *
  148.  * NetLERecvProcess --
  149.  *
  150.  *    Process a newly received packet.
  151.  *
  152.  * Results:
  153.  *    FAILURE if something went wrong, SUCCESS otherwise.
  154.  *
  155.  * Side effects:
  156.  *    None.
  157.  *
  158.  *----------------------------------------------------------------------
  159.  */
  160.  
  161. ReturnStatus
  162. NetLERecvProcess(dropPackets, statePtr)
  163.     Boolean        dropPackets;    /* Drop all packets. */
  164.     NetLEState        *statePtr;     /* The state of the interface. */
  165. {
  166.     register Address        descPtr;
  167.     register volatile short     *inBufPtr;
  168.     register short        *outBufPtr;
  169.     register unsigned        status;
  170.     register int        i;
  171.     int                size;
  172.     Boolean            tossPacket;
  173.  
  174.     /*
  175.      * If not initialized then forget the interrupt.
  176.      */
  177.     if (!statePtr->recvMemInitialized) {
  178.     return (FAILURE);
  179.     }
  180.  
  181.     descPtr = (Address)statePtr->recvDescNextPtr;
  182.  
  183.     status = *BUF_TO_ADDR(descPtr,NET_LE_RECV_STATUS);
  184.     /*
  185.      * First a few consistency check. 
  186.      */
  187.     if (status & NET_LE_RECV_CHIP_OWNED) {
  188.     printf("LE ethernet: Bogus receive interrupt. Buffer owned by chip.\n");
  189.     return (FAILURE);
  190.     }
  191.  
  192.     if (!(status & NET_LE_RECV_START_OF_PACKET)) {
  193.     printf(
  194.      "LE ethernet: Bogus receive interrupt. Buffer doesn't start packet.\n");
  195.     return (FAILURE);
  196.     }
  197.     /*
  198.      * Loop as long as there are packets to process.
  199.      */
  200.     tossPacket = dropPackets;
  201.     while (TRUE) {
  202.     /* 
  203.      * Check to see if we have processed all our buffers. 
  204.      */
  205.     if (status & NET_LE_RECV_CHIP_OWNED) {
  206.         break;
  207.     }
  208.     /*
  209.      * Since we allocated very large receive buffers all packets must fit
  210.      * in one buffer. Hence all buffers should have startOfPacket.
  211.      */
  212.     if (!(status & NET_LE_RECV_START_OF_PACKET)) {
  213.         printf("LE ethernet: Receive buffer doesn't start packet.\n");
  214.         return (FAILURE);
  215.     }
  216.     /*
  217.      * All buffers should also have an endOfPacket too.
  218.      */
  219.     if (!(status & NET_LE_RECV_END_OF_PACKET)) {
  220.         /* 
  221.          * If not an endOfPacket see if it was an error packet.
  222.          */
  223.         if (!(status & NET_LE_RECV_ERROR)) {
  224.         printf("LE ethernet: Receive buffer doesn't end packet.\n");
  225.         return (FAILURE);
  226.         }
  227.         /*
  228.          * We have got a serious error with a packet. 
  229.          * Report the error and toss the packet.
  230.          */
  231.         tossPacket = TRUE;
  232.         if (status & NET_LE_RECV_OVER_FLOW_ERROR) {
  233.         statePtr->stats.overrunErrors++;
  234.         printf("LE ethernet: Received packet with overflow error.\n");
  235.         }
  236.         /*
  237.          * Should probably panic on buffer errors.
  238.          */
  239.         if (status & NET_LE_RECV_BUFFER_ERROR) {
  240.         panic("LE ethernet: Received packet with buffer error.\n");
  241.         }
  242.     } else { 
  243.         /*
  244.          * The buffer had an endOfPacket bit set. Check for CRC errors and
  245.          * the like.
  246.          */
  247.         if (status & NET_LE_RECV_ERROR) {
  248.         tossPacket = TRUE;    /* Throw away packet on error. */
  249.         if (status & NET_LE_RECV_FRAMING_ERROR) {
  250.             statePtr->stats.frameErrors++;
  251.             printf(
  252.             "LE ethernet: Received packet with framing error.\n");
  253.         }
  254.         if (status & NET_LE_RECV_CRC_ERROR) {
  255.             statePtr->stats.crcErrors++;
  256.             printf("LE ethernet: Received packet with CRC error.\n");
  257.         }
  258.  
  259.          } 
  260.     }
  261.  
  262.     /* 
  263.      * Once we gotten here, it means that the buffer contains a packet
  264.      * and the tossPacket flags says if it is good or not.
  265.      */
  266.  
  267.     statePtr->stats.packetsRecvd++;
  268.  
  269.     /*
  270.      * Remove the CRC check (4 bytes) at the end of the packet.
  271.      */
  272.     size = *BUF_TO_ADDR(descPtr, NET_LE_RECV_PACKET_SIZE) - 4;
  273.     /*
  274.      * Copy the data out.
  275.      */
  276.  
  277.     inBufPtr = (volatile short *) CHIP_TO_BUF_ADDR(
  278.         *BUF_TO_ADDR(descPtr,NET_LE_RECV_BUF_ADDR_LOW) | 
  279.         ((*BUF_TO_ADDR(descPtr,NET_LE_RECV_STATUS) & 
  280.                 NET_LE_RECV_BUF_ADDR_HIGH) << 16));
  281.  
  282. #define COPY_IN(n) *(outBufPtr + n) = *(inBufPtr + (2 * n))
  283.  
  284.     outBufPtr = (short *)statePtr->recvBufPtr;
  285.     i = size;
  286.     while (i >= 64) {
  287.         COPY_IN(0);  COPY_IN(1);  COPY_IN(2);  COPY_IN(3);
  288.         COPY_IN(4);  COPY_IN(5);  COPY_IN(6);  COPY_IN(7);
  289.         COPY_IN(8);  COPY_IN(9);  COPY_IN(10); COPY_IN(11);
  290.         COPY_IN(12); COPY_IN(13); COPY_IN(14); COPY_IN(15);
  291.         COPY_IN(16); COPY_IN(17); COPY_IN(18); COPY_IN(19);
  292.         COPY_IN(20); COPY_IN(21); COPY_IN(22); COPY_IN(23);
  293.         COPY_IN(24); COPY_IN(25); COPY_IN(26); COPY_IN(27);
  294.         COPY_IN(28); COPY_IN(29); COPY_IN(30); COPY_IN(31);
  295.         outBufPtr += 32;
  296.         inBufPtr += 64;
  297.         i -= 64;
  298.     }
  299.     while (i >= 16) {
  300.         COPY_IN(0);  COPY_IN(1);  COPY_IN(2);  COPY_IN(3);
  301.         COPY_IN(4);  COPY_IN(5);  COPY_IN(6);  COPY_IN(7);
  302.         outBufPtr += 8;
  303.         inBufPtr += 16;
  304.         i -= 16;
  305.     }
  306.     while (i > 0) {
  307.         *outBufPtr = *inBufPtr;
  308.         outBufPtr++;
  309.         inBufPtr += 2;
  310.         i -= 2;
  311.     }
  312.     /*
  313.     * Call higher level protocol to process the packet.
  314.     */
  315.     if (!tossPacket) {
  316.         Net_Input(statePtr->interPtr,(Address)statePtr->recvBufPtr, size);
  317.     }
  318.     /*
  319.      * We're finished with it, give the buffer back to the chip. 
  320.      */
  321.     *BUF_TO_ADDR(descPtr,NET_LE_RECV_STATUS) |= NET_LE_RECV_CHIP_OWNED;
  322.  
  323.     /*
  324.      * Clear the interrupt bit for the packet we just got before 
  325.      * we check the ownership of the next packet. This prevents the 
  326.      * following race condition: We check the buffer and it is own
  327.      * by the chip; the chip gives the buffer to us and sets the
  328.      * interrupt; we clear the interrupt. 
  329.      * The fix is to always clear the interrupt and then check
  330.      * for owership as the chip sets owership and then sets the
  331.      * interrupt.
  332.      */
  333.  
  334.     *statePtr->regAddrPortPtr = NET_LE_CSR0_ADDR;
  335.     *statePtr->regDataPortPtr = 
  336.             NET_LE_CSR0_RECV_INTR | NET_LE_CSR0_INTR_ENABLE;
  337.  
  338.     /* 
  339.      * Check to see if we have processed all our buffers. 
  340.      */
  341.     descPtr = NEXT_RECV(descPtr);
  342.     status = *BUF_TO_ADDR(descPtr,NET_LE_RECV_STATUS);
  343.     if (status & NET_LE_RECV_CHIP_OWNED) {
  344.         break;
  345.     }
  346.     }
  347.  
  348.     /*
  349.      * Update the the ring pointer. We should be pointer at the chip owned 
  350.      * buffer in that the next packet will be put.
  351.      */
  352.  
  353.     statePtr->recvDescNextPtr = descPtr;
  354.  
  355.     /*
  356.      * RETURN a success.
  357.      */
  358.     return (SUCCESS);
  359. }
  360.